package com.chenbei.common.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chenbei.common.domain.Areas;
import com.chenbei.common.domain.vo.TreeNode;
import com.chenbei.common.mapper.AreasMapper;
import com.chenbei.common.service.IAreasService;
import com.chenbei.common.util.TreeNodeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.BasicHttpClientResponseHandler;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.impl.io.DefaultHttpRequestWriterFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class AreasService extends ServiceImpl<AreasMapper, Areas> implements IAreasService {
    @Override
    @Transactional
    public void init() {
        List<Areas> areasList = list();

        //初始化省份
        List<Areas> provinceList = remoteRequestProvinces();
        List<Areas> differenceSetProvinceList = differenceSet(areasList, provinceList);
        if (!differenceSetProvinceList.isEmpty()) {
            saveBatch(differenceSetProvinceList);

            //初始化城市
            for (Areas provinceAreas : provinceList) {
                List<Areas> cityList = remoteRequestCitiesByProvince(provinceAreas);
                List<Areas> differenceSetCityList = differenceSet(areasList, cityList);
                if (!differenceSetCityList.isEmpty()) {
                    saveBatch(differenceSetCityList);

                    //初始化区
                    if (cityList != null) {
                        for (Areas cityAreas : cityList) {
                            List<Areas> districtList = remoteRequestCitiesByDistrict(cityAreas);
                            if (districtList != null && !districtList.isEmpty()) {
                                saveBatch(districtList);
                            }
                        }
                    }
                }
            }
        }
    }

    @Override
    public List<Areas> listByPid(long pid) {
        LambdaQueryWrapper<Areas> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Areas::getPid, pid).orderByDesc(Areas::getSort);
        return list(lambdaQueryWrapper);
    }

    @Override
    public List<TreeNode<Areas>> tree(Long pid) {
        List<Areas> all = list();
        return buildTree(all, pid);
    }

    @Override
    public List<TreeNode<Areas>> provinceCityTree() {
        LambdaQueryWrapper<Areas> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(Areas::getLevel, Arrays.asList("1", "2"));
        List<Areas> list = list(lambdaQueryWrapper);
        return buildTree(list, 0L);
    }

    /**
     * 构建树形结构
     * @param areaList 集合
     * @return List
     */
    private List<TreeNode<Areas>> buildTree(List<Areas> areaList, Long pid) {
        if (areaList != null && !areaList.isEmpty()) {
            List<TreeNode<Areas>> treeNodeList = areaList.stream().map(areas -> {
                TreeNode<Areas> areasTreeNode = new TreeNode<>();
                areasTreeNode.setId(areas.getId());
                areasTreeNode.setPid(areas.getPid());
                areasTreeNode.setName(areas.getName());
                areasTreeNode.setTarget(areas);

                return areasTreeNode;
            }).collect(Collectors.toList());

            return TreeNodeUtil.buildTree(treeNodeList, pid);
        }

        return null;
    }

    /**
     * 远程请求省份数据
     * @return List
     */
    private List<Areas> remoteRequestProvinces() {
        String url = "http://datavmap-public.oss-cn-hangzhou.aliyuncs.com/areas/csv/100000_province.json";
        HttpGet httpGet = new HttpGet(url);
        try (CloseableHttpClient closeableHttpClient = HttpClients.createDefault()){
            String resp = closeableHttpClient.execute(httpGet, new BasicHttpClientResponseHandler());
            List<Areas> areasList = parseResponseData(resp, null);
            if (areasList != null && !areasList.isEmpty()) {
                return areasList.stream().peek(areas -> {
                    areas.setPid(0L);
                    areas.setLevel(1);

                }).collect(Collectors.toList());
            }
            return areasList;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 远程请求城市数据
     * @param provinceArea 省份区域信息
     * @return List
     */
    private List<Areas> remoteRequestCitiesByProvince(Areas provinceArea) {
        String url = "http://datavmap-public.oss-cn-hangzhou.aliyuncs.com/areas/csv/" + provinceArea.getAdCode() + "_city.json";
        HttpGet httpGet = new HttpGet(url);
        try (CloseableHttpClient closeableHttpClient = HttpClients.createDefault()){
            String resp = closeableHttpClient.execute(httpGet, new BasicHttpClientResponseHandler());
            List<Areas> areasList = parseResponseData(resp, provinceArea);
            if (areasList != null && !areasList.isEmpty()) {
                return areasList.stream().peek(areas -> {
                    areas.setPid(provinceArea.getId());
                    areas.setLevel(2);
                }).collect(Collectors.toList());
            }

            return areasList;
        } catch (IOException e) {
            log.error("{}", e.getMessage());
        }
        return null;
    }

    /**
     * 远程请求县数据
     * @param cityAreas 城市区域信息
     * @return List
     */
    private List<Areas> remoteRequestCitiesByDistrict(Areas cityAreas) {
        String url = "http://datavmap-public.oss-cn-hangzhou.aliyuncs.com/areas/csv/" + cityAreas.getAdCode() + "_district.json";
        HttpGet httpGet = new HttpGet(url);
        try (CloseableHttpClient closeableHttpClient = HttpClients.createDefault()){
            String resp = closeableHttpClient.execute(httpGet, new BasicHttpClientResponseHandler());
            List<Areas> areasList = parseResponseData(resp, cityAreas);
            if (areasList != null && !areasList.isEmpty()) {
                return areasList.stream().peek(areas -> {
                    areas.setPid(cityAreas.getId());
                    areas.setLevel(3);
                }).collect(Collectors.toList());
            }

            return areasList;
        } catch (IOException e) {
            log.error("{}", e.getMessage());
        }
        return null;
    }

    /**
     * 解析响应数据
     * @param responseData 响应数据
     * @return List
     */
    private List<Areas> parseResponseData(String responseData, Areas parentArea) {
        if (StrUtil.isNotBlank(responseData)) {
            JSONObject jsonObject = JSON.parseObject(responseData);
            if (jsonObject.containsKey("rows")) {
                String dataStr = jsonObject.getString("rows");
                if (StrUtil.isNotBlank(dataStr)) {
                    JSONArray jsonArray = JSON.parseArray(dataStr);

                    List<Areas> areasList = new ArrayList<>();
                    for (int i = 0; i < jsonArray.size(); i++) {
                        JSONObject jsonObject1 = jsonArray.getJSONObject(i);

                        Areas areas = new Areas();
                        areas.setAdCode(jsonObject1.containsKey("adcode") ? jsonObject1.getString("adcode") : "");
                        areas.setLng(jsonObject1.containsKey("lng") ? jsonObject1.getString("lng") : "");
                        areas.setLat(jsonObject1.containsKey("lat") ? jsonObject1.getString("lat") : "");
                        areas.setName(jsonObject1.containsKey("name") ? jsonObject1.getString("name") : "");
                        areas.setCreateTime(LocalDateTime.now());

                        if (parentArea != null) {
                            if (jsonObject1.containsKey("parent") && jsonObject1.getString("parent").equals(parentArea.getName())) {
                                areasList.add(areas);
                            }
                        } else {
                            areasList.add(areas);
                        }
                    }

                    return areasList;
                }
            }
        }
        return null;
    }

    /**
     * 获取差集
     * @param source 原始数据
     * @param data 新数据
     * @return 差集集合
     */
    private List<Areas> differenceSet(List<Areas> source, List<Areas> data) {
        List<Areas> differenceSet = new ArrayList<>();

        if (source == null || source.isEmpty()) {
            differenceSet.addAll(data);
        } else {
            for (Areas areas : data) {
                boolean exist = false;
                for (Areas areas1 : source) {
                    if (areas1.getAdCode().equals(areas.getAdCode())) {
                        exist = true;
                        break;
                    }
                }

                if (!exist) {
                    differenceSet.add(areas);
                }
            }
        }


        return differenceSet;
    }
}
